package com.pmpd.activity.controller.api;

import com.dmap.base.constants.Constant;
import com.dmap.base.send.email.MailService;
import com.dmap.base.units.DateUtil;
import com.dmap.base.vo.BaseVo;
import com.pmpd.activity.constants.ActivityConstant;
import com.pmpd.activity.controller.api.param.ActivityProgressParam;
import com.pmpd.activity.bo.api.RunDistanceBo;
import com.pmpd.activity.bo.api.StepAndSleepInfoBo;
import com.pmpd.activity.po.ActivityProgress;
import com.pmpd.activity.po.ActivityTask;
import com.pmpd.activity.po.ActivityUser;
import com.pmpd.activity.rpc.ActivityPlanRpc;
import com.pmpd.activity.rpc.ActivityRunRpc;
import com.pmpd.activity.rpc.ActivitySenorRpc;
import com.pmpd.activity.rpc.param.ActivityTaskAlarmInfoParam;
import com.pmpd.activity.service.api.ApiActivityProgressService;
import com.pmpd.activity.service.api.ApiActivityUserService;
import com.pmpd.activity.service.api.impl.ApiActivityUserServiceImpl;
import com.pmpd.activity.vo.api.ApiActivityProgressVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.mail.MessagingException;
import javax.validation.Valid;
import java.util.ArrayList;
import java.util.List;

/**
 * @Author liuying
 * @Description 活动参与者每日进度控制层
 * @Date 15:07 2018/6/7
 */
@Api(value = "App/活动进度API", description = "App/活动进度API")
@RestController
@RequestMapping(value = "/api/pmpd-activity-server/v1/activity/activityProgress")
public class ApiActivityProgressController {

    @Value("spring.profiles.active")
    private String environment;

    private static final Logger logger = LoggerFactory.getLogger(ApiActivityProgressController.class);

    @Resource
    private ApiActivityProgressService apiActivityProgressService;

    @Resource
    private ActivitySenorRpc activitySenorRpc;

    @Resource
    private ActivityRunRpc activityRunRpc;

    @Resource
    private ActivityPlanRpc activityPlanRpc;

    @Resource
    private ApiActivityUserService apiActivityUserService;

    @ResponseBody
    @ApiOperation(value = "获取用户当日任务完成情况", notes = "1. 会同步跑步、计步和睡眠数据\n" +
            "\n" +
            "2. 返回为空，则无今日任务")
    @RequestMapping(value = "/select/selectDailyData", method = RequestMethod.POST)
    public BaseVo selectDailyData(@RequestBody ActivityProgressParam param) {
        long seconds = System.currentTimeMillis() / 1000;

        BaseVo baseVo = new BaseVo();
        if (param == null || StringUtils.isEmpty(param.getActivityId()) || Long.parseLong(param.getActivityId()) == 0
                || StringUtils.isEmpty(param.getUserId()) || Long.parseLong(param.getUserId()) == 0) {
            baseVo.setCode(Constant.RESPONSE_PARAM_ERROR_CODE);
            baseVo.setMsg(Constant.RESPONSE_PARAM_ERROR_MSG);
            return baseVo;
        }

        //得到用户当日任务
        long userId = Long.parseLong(param.getUserId());
        long activityId = Long.parseLong(param.getActivityId());
        ActivityTask task = apiActivityProgressService.getProgress(activityId, userId, seconds);
        //如果无任务则返回null
        if (task == null) {
            baseVo.setCode(ActivityConstant.RESPONSE_NO_DATA_ERROR_CODE);
            baseVo.setMsg(ActivityConstant.RESPONSE_NO_DATA_ERROR_MSG);
            return baseVo;
        }

        List<Long> userIds = new ArrayList<>();
        userIds.add(userId);
        int runData = 0, sleepData = 0, stepData = 0;
        List<StepAndSleepInfoBo> sleepDataList = activitySenorRpc.selectSleepAndStep(userIds, DateUtil.getDay0ByTime(seconds), ActivityConstant.STATE_SLEEP);
        List<StepAndSleepInfoBo> stepDataList = activitySenorRpc.selectSleepAndStep(userIds, DateUtil.getDay0ByTime(seconds), ActivityConstant.STATE_STEP);
        List<RunDistanceBo> runDataList = activityRunRpc.selectRunData(userIds, DateUtil.getDay0ByTime(seconds));
        if (CollectionUtils.isNotEmpty(sleepDataList)) {
            sleepData = sleepDataList.get(0).getSleepTime();
        }
        if (CollectionUtils.isNotEmpty(stepDataList)) {
            stepData = stepDataList.get(0).getStepNumber();
        }
        if (CollectionUtils.isNotEmpty(runDataList)) {
            runData = runDataList.get(0).getDistance();
        }

        //同步数据到progress表，并更新完成状态
        ActivityProgress progressParam = new ActivityProgress();
        progressParam.setUserId(userId);
        progressParam.setActivityId(activityId);
        progressParam.setTaskTime(DateUtil.getDay0ByTime(seconds));
        progressParam.setSleepNumber(sleepData);
        progressParam.setStepNumber(stepData);
        progressParam.setRunNumber(runData);
        ActivityProgress activityProgress = apiActivityProgressService.synchrodata(progressParam);
        if (activityProgress == null) {
            baseVo.setCode(ActivityConstant.RESPONSE_DATA_SYNCHRONOUS_ERROR_CODE);
            baseVo.setMsg(ActivityConstant.RESPONSE_DATA_SYNCHRONOUS_ERROR_MSG);
            return baseVo;
        }

        //同步完成天数到user表
        int finishDays = apiActivityProgressService.getFinishDays(userId, activityId);
        ActivityUser activityUser = apiActivityUserService.updateFinishDays(userId, activityId, finishDays);
        if (activityUser == null) {
            baseVo.setCode(Constant.RESPONSE_UPDATE_ERROR_CODE);
            baseVo.setMsg(Constant.RESPONSE_UPDATE_ERROR_MSG);
            return baseVo;
        }

        //分割、拼接任务完成情况字符串
        String progressComment = null;
        String[] splites = task.getComment().split("\\d+");//根据数字分割
        if (splites.length == ActivityConstant.LENGTH_RUN_TASK_COMMENT_SPLITE) {
            progressComment = splites[0] + String.format("%.1f", runData * 1.0 / 1000) + "km/"
                    + task.getRunGoal() / 1000 + splites[1];
        } else if (splites.length == ActivityConstant.LENGTH_STEP_TASK_COMMENT_SPLITE) {
            progressComment = splites[0] + stepData + "步/" + task.getStepGoal() + splites[1]
                    + String.format("%.1f", sleepData * 1.0 / 60) + "H/" + task.getSleepGoal() / 60 + splites[2];
        }

        //封装返回数据
        ApiActivityProgressVo progressVo = new ApiActivityProgressVo();
        progressVo.setProgressComment(progressComment);
        progressVo.setCompleteState(activityProgress.getStatus());
        baseVo.setData(progressVo);

        return baseVo;
    }

    @ResponseBody
    @ApiOperation(value = "获取用户明日任务", notes = "1.返回为null，则表示无明日任务")
    @RequestMapping(value = "/select/selectNextDayTask", method = RequestMethod.POST)
    public BaseVo selectNextDayTask(@RequestBody ActivityProgressParam param) {
        BaseVo baseVo = new BaseVo();
        if (param == null || StringUtils.isEmpty(param.getActivityId()) || Long.parseLong(param.getActivityId()) == 0
                || StringUtils.isEmpty(param.getUserId()) || Long.parseLong(param.getUserId()) == 0) {
            baseVo.setCode(Constant.RESPONSE_PARAM_ERROR_CODE);
            baseVo.setMsg(Constant.RESPONSE_PARAM_ERROR_MSG);
            return baseVo;
        }

        long seconds = System.currentTimeMillis() / 1000;
        ActivityTask task = apiActivityProgressService.getProgress(Long.parseLong(param.getActivityId()), Long.parseLong(param.getUserId()), DateUtil.getDay24ByTime(seconds) + 1);
        if (task == null) {
            baseVo.setData(null);
            return baseVo;
        }

        baseVo.setData(task.getComment());
        return baseVo;
    }

    @ResponseBody
    @ApiOperation(value = "判断是否已设置任务提醒", notes = "\n" +
            "1. 判断是否有明日任务提醒，false为未设置，true为已设置")
    @RequestMapping(value = "/isAddTaskManager", method = RequestMethod.POST)
    public BaseVo isAddTaskManager(@RequestBody ActivityProgressParam param) {
        BaseVo baseVo = new BaseVo();
        if (param == null || StringUtils.isEmpty(param.getActivityId()) || Long.parseLong(param.getActivityId()) == 0
                || StringUtils.isEmpty(param.getUserId()) || Long.parseLong(param.getUserId()) == 0) {
            baseVo.setCode(Constant.RESPONSE_PARAM_ERROR_CODE);
            baseVo.setMsg(Constant.RESPONSE_PARAM_ERROR_MSG);
            return baseVo;
        }

        //判断缓存里是否存在当天任务提醒
        String value = apiActivityProgressService.isSetTaskAlarm(param);
        if (StringUtils.isEmpty(value)){
            baseVo.setData(false);
        } else {
            baseVo.setData(true);
        }
        return baseVo;
    }

    @Transactional
    @ResponseBody
    @ApiOperation(value = "设置明日任务提醒和判断是否已设置任务提醒", notes = "\n" +
            "1. 判断是否有明日任务提醒，有则msg为\"成功\"，data返回id;\n" +
            "\n" +
            "2. 设置明日任务提醒，设置成功msg为\"成功\"，data无返回;\n")
    @RequestMapping(value = "/add/addTaskManager", method = RequestMethod.POST)
    public BaseVo addTaskManager(@RequestBody ActivityProgressParam param) {
        long seconds = System.currentTimeMillis() / 1000;

        BaseVo baseVo = new BaseVo();
        if (param == null || StringUtils.isEmpty(param.getActivityId()) || Long.parseLong(param.getActivityId()) == 0
                || StringUtils.isEmpty(param.getUserId()) || Long.parseLong(param.getUserId()) == 0) {
            baseVo.setCode(Constant.RESPONSE_PARAM_ERROR_CODE);
            baseVo.setMsg(Constant.RESPONSE_PARAM_ERROR_MSG);
            return baseVo;
        }

        //判断缓存里是否存在当天任务提醒
        String value = apiActivityProgressService.isSetTaskAlarm(param);
        if (StringUtils.isNotEmpty(value)) {
            baseVo.setData(param.getUserId());
            return baseVo;
        }

        //查询用户明日任务
        ActivityTaskAlarmInfoParam infoParam = new ActivityTaskAlarmInfoParam();
        ActivityTask task = apiActivityProgressService.getProgress(Long.parseLong(param.getActivityId()), Long.parseLong(param.getUserId()), DateUtil.getDay24ByTime(seconds) + 1);
        if (task == null) {
            baseVo.setCode(ActivityConstant.RESPONSE_NO_DATA_ERROR_CODE);
            baseVo.setMsg(ActivityConstant.RESPONSE_NO_DATA_ERROR_MSG);
            return baseVo;
        }
        infoParam.setName(task.getComment());

        infoParam.setUserId(Long.parseLong(param.getUserId()));
        infoParam.setRemind(ActivityConstant.DEFAULT_REMIND);//默认提醒
        infoParam.setRemindTime(DateUtil.getDay24ByTime(seconds) + 1 + ActivityConstant.DEFAULT_REMIND_TIME);//默认为第二天15:00
        infoParam.setLevel(ActivityConstant.DEFAULT_LEVEL);//默认重要
        infoParam.setRepeatNumber(ActivityConstant.DEFAULT_REPEAT_NUMBER);//默认永不
        infoParam.setRepeatType(ActivityConstant.DEFAULT_REPEAT_TYPE);//默认永不
        infoParam.setNote(infoParam.getName());//默认和名称一样
        infoParam.setStatus(ActivityConstant.DEFAULT_STATUS);//默认未完成

        boolean success = activityPlanRpc.setTaskAlarm(infoParam);
        if (!success) {
            baseVo.setCode(ActivityConstant.RESPONSE_RPC_GET_DATA_ERROR_CODE);
            baseVo.setMsg(ActivityConstant.RESPONSE_RPC_GET_DATA_ERROR_MSG);
            return baseVo;
        }

        //任务提醒信息放入缓存中
        boolean redisSuccess = apiActivityProgressService.addTaskAlarm(param);
        if (!redisSuccess) {
            baseVo.setCode(ActivityConstant.RESPONSE_REDIS_INSERT_ERROR_CODE);
            baseVo.setMsg(ActivityConstant.RESPONSE_REDIS_INSERT_ERROR_MSG);
            return baseVo;
        }

        return baseVo;
    }

    @ResponseBody
    @ApiOperation(value = "新增某活动所有用户每日进程", notes = "新增某活动所有用户每日进程")
    @RequestMapping(value = "/add/bulkInsertProgress", method = RequestMethod.POST)
    public void bulkInsertProgress() {
        try {
            //查出所有参加活动的用户
            List<ActivityUser> activityUsers = apiActivityUserService.selectByActivityId(ActivityConstant.SEVEN_DAYS_TRAINING_ID);

            //批量放入progress表中
            if (CollectionUtils.isNotEmpty(activityUsers)){
                apiActivityProgressService.bulkInsert(activityUsers);
            }

            try {
                MailService.sendMail(ActivityConstant.EMAIL_ADDRESS, ActivityConstant.EMAIL_SUBJECT + environment, "七天养成计划-新增某活动所有用户每日进程成功");
            } catch (MessagingException me) {
                logger.error("七天养成计划-新增某活动所有用户每日进程定时任务成功信息 MailService.sendMail error:  {}", me);
            }
        } catch (Exception e) {
            try {
                MailService.sendMail(ActivityConstant.EMAIL_ADDRESS, ActivityConstant.EMAIL_SUBJECT + environment, "七天养成计划-新增某活动所有用户每日进程 error: " + e);
            } catch (MessagingException me) {
                logger.error("七天养成计划-新增某活动所有用户每日进程定时任务error信息 MailService.sendMail error:  {}", me);
            }
        }
    }

    @ResponseBody
    @ApiOperation(value = "更新某活动所有用户计步、睡眠和跑步数据", notes = "更新某活动所有用户计步、睡眠和跑步数据")
    @RequestMapping(value = "/update/bulkUpdateProgress", method = RequestMethod.POST)
    public void bulkUpdateProgress() {
        try {
            //批量更新数据到progress表中
            apiActivityProgressService.bulkUpdate();

            //批量获取用户活动完成天数
            List<ActivityUser> users = apiActivityProgressService.getBulkProgress(ActivityConstant.SEVEN_DAYS_TRAINING_ID, ActivityConstant.STATE_PROGRESS_COMPLETE);

            //批量更新完成天数到user表中
            apiActivityUserService.bulkUpdate(users);

            try {
                MailService.sendMail(ActivityConstant.EMAIL_ADDRESS, ActivityConstant.EMAIL_SUBJECT + environment, "七天养成计划-更新某活动所有用户计步、睡眠和跑步数据成功");
            } catch (MessagingException me) {
                logger.error("七天养成计划-更新某活动所有用户计步、睡眠和跑步数据成功信息 MailService.sendMail error:  {}", me);
            }
        } catch (Exception e) {
            try {
                MailService.sendMail(ActivityConstant.EMAIL_ADDRESS, ActivityConstant.EMAIL_SUBJECT + environment, "七天养成计划-更新某活动所有用户计步、睡眠和跑步数据 error: " + e);
            } catch (MessagingException me) {
                logger.error("七天养成计划-更新某活动所有用户计步、睡眠和跑步数据error信息 MailService.sendMail error:  {}", me);
            }
        }
    }

}
